package session;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import logging.transaction.TransactionLogger;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
import security.auth.UserManager;
import sql.SQLStatementSplitter;
import sql.executor.SQLExecutor;
import sql.parser.SQLParser;
import storage.StorageException;

/**
 * Session 接口，表示用户登录后的会话状态
 * 每个用户登录后都会创建一个新的会话实例
 * 会话可以操作多个数据库，currentDatabase只是当前默认的数据库上下文
 */
public class Session {
    // 会话唯一标识符
    private final String sessionId;

    // 用户信息
    private final String username;
    private final int userLevel;

    // 当前默认数据库（可随时切换）
    private String currentDatabaseName;
    private String currentDatabaseOwnerName;
    private final LocalDateTime createTime;

    // 当前线程的会话存储
    private static final ThreadLocal<Session> currentSession = new ThreadLocal<>();

    /**
     * 创建新会话
     *
     * @param username 用户名
     * @param userLevel 用户权限级别
     */
    public Session(String username, int userLevel) {
        this.sessionId = UUID.randomUUID().toString();
        this.username = username;
        this.userLevel = userLevel;

        // 根据用户权限设置默认数据库
        if (userLevel == UserManager.ADMIN_LEVEL) {
            this.currentDatabaseName = "system_db"; // 管理员默认使用系统数据库
            this.currentDatabaseOwnerName = "system"; // Assuming "system" is the owner of system_db
        } else {
            this.currentDatabaseName = null; // 普通用户默认没有数据库
            this.currentDatabaseOwnerName = null;
        }

        this.createTime = LocalDateTime.now();

        System.out.println("✅ 创建会话: 用户=" + username + ", 权限=" +
                (userLevel == UserManager.ADMIN_LEVEL ? "管理员" : "普通用户") +
                ", 默认数据库=" + (this.currentDatabaseName != null ? this.currentDatabaseOwnerName + "." + this.currentDatabaseName : "无"));
    }

    /**
     * 将当前会话设置为线程本地会话
     */
    public void activate() {
        currentSession.set(this);
        // 同时更新DatabaseManager中的当前用户
        storage.manager.DatabaseManager.setCurrentUser(this.username);
    }

    /**
     * 清除线程本地会话
     */
    public void deactivate() {
        currentSession.remove();
        // 同时清除DatabaseManager中的当前用户
        storage.manager.DatabaseManager.setCurrentUser(null);
    }

    /**
     * 获取当前线程的会话
     *
     * @return 当前会话，如果没有活动会话则返回null
     */
    public static Session getCurrentSession() {
        return currentSession.get();
    }

    /**
     * 获取当前线程的用户名
     *
     * @return 当前用户名，如果没有活动会话则返回null
     */
    public static String getCurrentUser() {
        Session session = currentSession.get();
        return session != null ? session.getUsername() : null;
    }

    /**
     * 获取会话当前默认数据库名称
     */
    public String getCurrentDatabaseName() {
        return this.currentDatabaseName;
    }

    /**
     * 获取会话当前默认数据库的所有者名称
     */
    public String getCurrentDatabaseOwnerName() {
        return this.currentDatabaseOwnerName;
    }

    /**
     * 设置会话当前默认数据库
     * 用户可以在同一会话中通过此方法切换操作的数据库
     *
     * @param ownerName 数据库所有者的名称
     * @param databaseName 数据库名称
     * @return 切换成功返回true，失败返回false
     */
    public boolean setCurrentDatabase(String ownerName, String databaseName) {
        System.out.println("[Session.setCurrentDatabase] Attempting to set current DB. Owner: '" + 
                          (ownerName == null ? "null" : ownerName) + "', DB Name: '" +
                          (databaseName == null ? "null" : databaseName) + "'");

        // 如果传入null，表示清除当前数据库
        if (databaseName == null) { // ownerName can be null too if dbName is null
            this.currentDatabaseName = null;
            this.currentDatabaseOwnerName = null;
            // 同步更新DatabaseManager - assuming new signature
            storage.manager.DatabaseManager.setCurrentDatabase(null, null);
            System.out.println("✅ 已清除当前数据库");
            return true;
        }
        
        if (ownerName == null || ownerName.trim().isEmpty()) {
             System.err.println("❌ 数据库所有者名称不能为空");
             return false;
        }


        // 验证数据库是否存在 - assuming new signature
        if (!storage.manager.DatabaseManager.databaseExists(ownerName, databaseName)) {
            System.err.println("❌ 数据库 [" + ownerName + "." + databaseName + "] 不存在");
            return false;
        }

        // 验证用户是否有权限访问该数据库 - assuming new signature for checkDatabaseAccess
        if (!checkDatabaseAccess(ownerName, databaseName)) {
            System.err.println("❌ 用户 [" + this.username + "] 无权限访问数据库 [" + ownerName + "." + databaseName + "]");
            return false;
        }

        // 切换会话数据库
        this.currentDatabaseName = databaseName;
        this.currentDatabaseOwnerName = ownerName;

        // 同步更新DatabaseManager中的当前数据库 - assuming new signature
        storage.manager.DatabaseManager.setCurrentDatabase(ownerName, databaseName);

        System.out.println("✅ 会话已切换至数据库: " + ownerName + "." + databaseName);
        return true;
    }

    /**
     * 获取会话用户名
     */
    public String getUsername() {
        return this.username;
    }

    /**
     * 获取用户权限级别
     */
    public int getUserLevel() {
        return this.userLevel;
    }

    /**
     * 获取会话ID
     */
    public String getSessionId() {
        return this.sessionId;
    }

    /**
     * 执行可能包含多条语句的SQL字符串。
     * 语句之间应以分号分隔。
     *
     * @param batchSql 包含一条或多条SQL语句的字符串
     * @return 通常返回最后一条成功执行的语句的状态码，或在批处理中任何语句失败时返回-1。
     *         注意：返回值的具体含义（例如，总影响行数 vs 最后状态）可能需要根据应用需求调整。
     */
    public int executeUpdate(String batchSql) {
        System.out.println("接收到SQL: " + batchSql); // Log the original input
        
        // 使用新的分割器分割语句
        List<String> statements;
        try {
            statements = SQLStatementSplitter.split(batchSql);
            if (statements.isEmpty() && batchSql != null && !batchSql.trim().isEmpty()){
                // If input was not empty but split resulted in nothing, it might indicate an issue
                // or just comments/whitespace. Log a debug message.
                System.out.println("[DEBUG] SQL input contained no executable statements after splitting.");
                return 0; // Or appropriate code for no-op
            }
             if (statements.isEmpty()) {
                 return 0; // Nothing to execute
             }
             
            // 添加调试日志，检查分割后的语句
            System.out.println("[DEBUG Session] 分割后的语句列表:");
            for (int i = 0; i < statements.size(); i++) {
                System.out.println("[DEBUG Session] 语句 " + (i + 1) + ": '" + statements.get(i) + "'");
                // 检查语句是否包含分号
                if (statements.get(i).contains(";")) {
                    System.out.println("[DEBUG Session] 警告：语句 " + (i + 1) + " 包含分号！");
                }
            }
        } catch (Exception e) {
            System.err.println("❌ SQL语句分割失败: " + e.getMessage());
            // Optionally log stack trace for debugging splitter issues
            // e.printStackTrace(); 
            return -1;
        }
        
        System.out.println("分割得到 " + statements.size() + " 条语句，准备逐条执行...");

        int overallAffectedRows = 0; // Or use last status code
        int lastStatementResult = 0;
        int statementCount = 0;

        for (String sql : statements) {
            statementCount++;
            String trimmedSql = sql.trim(); // Trim each statement
            if (trimmedSql.isEmpty()) {
                System.out.println("[DEBUG] 跳过第 " + statementCount + " 条空语句。");
                continue; // Skip empty statements resulting from split (e.g., trailing semicolons)
            }

            System.out.println("执行第 " + statementCount + " 条: " + trimmedSql);
            
            // --- Begin single statement execution logic (adapted from previous version) ---
            try {
                // 处理CREATE DATABASE语句的特殊情况
                if (trimmedSql.toUpperCase().startsWith("CREATE DATABASE")) {
                    lastStatementResult = handleCreateDatabase(trimmedSql);
                    if (lastStatementResult < 0) return -1; // Stop batch on failure
                    if (lastStatementResult > 0) {
                        overallAffectedRows++; // Count DDL as 1 affected (or adjust as needed)
                    }
                    continue; // Move to next statement
                }

                // 处理USE DATABASE语句
                if (trimmedSql.toUpperCase().startsWith("USE")) {
                    lastStatementResult = handleUseDatabase(trimmedSql);
                    if (lastStatementResult < 0) return -1; // Stop batch on failure
                    overallAffectedRows++; // Count as 1 affected
                    continue; 
                }

                // 处理 GRANT 语句 (允许在事务外执行)
                if (trimmedSql.toUpperCase().startsWith("GRANT ")) {
                    System.out.println("[INFO] Session: Detected GRANT statement. Executing outside of transaction check.");
                    lastStatementResult = SQLParser.executeUpdate(trimmedSql);
                    if (lastStatementResult < 0) {
                        throw new Exception("语句 " + statementCount + " ('" + trimmedSql + "') 执行 GRANT 失败，由SQLParser报告。");
                    }
                    overallAffectedRows += (lastStatementResult > 0 ? lastStatementResult : 1); // Consider GRANT successful as 1 affected row if 0
                    continue;
                }

                // 处理 REVOKE 语句 (允许在事务外执行)
                if (trimmedSql.toUpperCase().startsWith("REVOKE ")) {
                    System.out.println("[INFO] Session: Detected REVOKE statement. Executing outside of transaction check.");
                    lastStatementResult = SQLParser.executeUpdate(trimmedSql);
                    if (lastStatementResult < 0) {
                        throw new Exception("语句 " + statementCount + " ('" + trimmedSql + "') 执行 REVOKE 失败，由SQLParser报告。");
                    }
                    overallAffectedRows += (lastStatementResult > 0 ? lastStatementResult : 1); // Consider REVOKE successful as 1 affected row if 0
                    continue;
                }

                // 处理 COMMIT 语句
                if (trimmedSql.toUpperCase().startsWith("COMMIT")) {
                    try {
                        TransactionLogger.getInstance().commitTransaction();
                        System.out.println("✅ 事务已提交 (语句 " + statementCount + ")。");
                        this.setCurrentDatabase(null, null); 
                        lastStatementResult = 1; // Indicate success
                        overallAffectedRows++;
                    } catch (IllegalStateException e) { 
                        System.err.println("❌ 提交事务失败 (语句 " + statementCount + "): " + e.getMessage());
                        this.setCurrentDatabase(null, null);
                        lastStatementResult = -1;
                        return -1; // Stop batch on failure
                    } catch (Exception e) { 
                        System.err.println("❌ 提交事务时发生严重错误 (语句 " + statementCount + "): " + e.getMessage());
                        System.err.println("数据库可能处于不一致状态。请联系管理员检查。");
                        this.setCurrentDatabase(null, null); 
                        lastStatementResult = -1;
                        return -1; // Stop batch on failure
                    }
                    continue;
                }

                // 处理 ROLLBACK 语句
                if (trimmedSql.toUpperCase().startsWith("ROLLBACK")) {
                    try {
                        TransactionLogger.getInstance().rollbackTransaction(); 
                        System.out.println("✅ 事务已回滚 (语句 " + statementCount + ")。");
                        this.setCurrentDatabase(null, null); 
                        lastStatementResult = 1; // Indicate success
                        overallAffectedRows++;
                    } catch (IllegalStateException e) { 
                        System.err.println("❌ 回滚事务失败 (语句 " + statementCount + "): " + e.getMessage());
                        this.setCurrentDatabase(null, null); 
                        lastStatementResult = -1;
                        return -1; // Stop batch on failure
                    } catch (Exception e) { 
                        System.err.println("❌ 回滚事务时发生严重错误 (语句 " + statementCount + "): " + e.getMessage());
                        this.setCurrentDatabase(null, null); 
                        lastStatementResult = -1;
                        return -1; // Stop batch on failure
                    }
                    continue;
                }

                // 对于其他SQL (DML/DDL)，需要事务
                if (!TransactionLogger.getInstance().isTransactionActive()) {
                    System.err.println("错误: SQL操作 \"" + trimmedSql + "\" (语句 " + statementCount + ") 需要在活动的事务中执行。请先使用 'USE database' 命令。");
                    return -1; // Stop batch on failure
                }
                
                String activeTxDbName = TransactionLogger.getInstance().getTransactionDatabaseName();
                if (this.currentDatabaseName == null || !this.currentDatabaseName.equals(activeTxDbName)) {
                     System.err.println("错误: 会话与活动事务数据库不匹配 (语句 " + statementCount + ")。 Session='" + this.currentDatabaseName + "', Tx='" + activeTxDbName + "'。正在回滚。");
                     try { TransactionLogger.getInstance().rollbackTransaction(); } catch (Exception rbEx) { /* ignore */ }
                     this.setCurrentDatabase(null, null); 
                     return -1;
                }
                
                // 修改点：区分 SELECT 和其他更新语句
                if (trimmedSql.toUpperCase().startsWith("SELECT")) {
                    System.out.println("[INFO] Detected SELECT statement in executeUpdate batch (statement " + statementCount + "). Executing as query...");
                    System.out.println("--- Executing Query: " + trimmedSql + " ---");
                    List<String[]> queryResults = SQLParser.executeQuery(trimmedSql); // SQLParser.executeQuery handles its own exceptions for SELECT
                    
                    // 打印查询结果 (SQLParser.executeQuery 内部也可能打印，这里可以补充或调整)
                    if (queryResults != null && !queryResults.isEmpty()) {
                        System.out.println("--- Query Results (Statement " + statementCount + ") ---");
                        for (String[] row : queryResults) {
                            System.out.println(Arrays.toString(row));
                        }
                        System.out.println("--- End of Query Results (Statement " + statementCount + ") ---");
                        lastStatementResult = queryResults.size(); // 代表返回的行数，但不计入 overallAffectedRows
                    } else {
                        System.out.println("[INFO] Query (Statement " + statementCount + ") returned no results or failed (see logs from SQLParser/SQLExecutor).");
                        lastStatementResult = 0; 
                    }
                    // SELECT 语句不修改 overallAffectedRows
                } else {
                    // 对于非 SELECT 语句 (DML/DDL)，调用 SQLParser.executeUpdate
                    lastStatementResult = SQLParser.executeUpdate(trimmedSql); 
                    if (lastStatementResult < 0) { 
                        // Error message is likely printed within SQLParser or lower layers
                        // The catch block below will handle rollback and stop the batch.
                        throw new Exception("语句 " + statementCount + " ('" + trimmedSql + "') 执行失败，由SQLParser报告。");
                    }
                    overallAffectedRows += lastStatementResult; // Accumulate affected rows for DML/DDL
                }

            } catch (Exception e) { // Catch failure for the current single statement
                System.err.println("执行第 " + statementCount + " 条语句失败: '" + trimmedSql + "' - " + e.getMessage());
                
                if (TransactionLogger.getInstance().isTransactionActive()) {
                    System.err.println("由于执行语句失败，正在回滚活动事务...");
                    try {
                        TransactionLogger.getInstance().rollbackTransaction();
                        this.setCurrentDatabase(null, null); // Also clear session context on rollback
                        System.err.println("活动事务已回滚。批处理中止。");
                    } catch (Exception exRollback) {
                        System.err.println("尝试回滚事务时也发生错误: " + exRollback.getMessage());
                    }
                } else {
                    System.err.println("语句执行失败，且当前无活动事务。");
                }
                return -1; // Stop the entire batch execution on any failure
            }
            // --- End single statement execution logic ---
        } // End of loop through statements

        System.out.println("✅ SQL批处理执行完成。总影响行数 (近似): " + overallAffectedRows); 
        // Return the result of the last statement, or a summary status.
        // Returning overallAffectedRows or simply 1 for success might be better alternatives.
        // Let's return 1 if all statements executed without throwing an exception leading to return -1.
        return 1; // Indicates batch completed without aborting
    }

    /**
     * 执行需要返回数据的SQL语句
     * 如果SQL语句没有明确指定数据库，则使用当前默认数据库
     * 如果SQL包含多个语句，将执行所有语句并返回最后一个语句的结果
     *
     * @param sql SQL语句
     * @return 查询结果集
     */
    public ArrayList<ArrayList<String>> executeQuery(String sql) {
        System.out.println("执行: " + sql);
        try {
            if (currentDatabaseName == null) {
                throw new Exception("请先选择数据库");
            }
            
            // 使用 SQLStatementSplitter 分割多个语句
            List<String> statements = SQLStatementSplitter.split(sql);
            if (statements.isEmpty()) {
                throw new Exception("SQL语句为空");
            }
            
            System.out.println("[DEBUG Session.executeQuery] 分割得到 " + statements.size() + " 条语句，准备逐条执行...");
            
            // 执行所有语句，返回最后一个语句的结果
            List<String[]> results = null;
            int statementCount = 0;
            
            for (String stmt : statements) {
                statementCount++;
                String trimmedStmt = stmt.trim();
                if (trimmedStmt.isEmpty()) {
                    continue;
                }
                
                System.out.println("[DEBUG Session.executeQuery] 执行第 " + statementCount + " 条: " + trimmedStmt);
                results = SQLParser.executeQuery(trimmedStmt);
                
                // 如果不是最后一个语句，打印结果但不返回
                if (statementCount < statements.size()) {
                    System.out.println("--- 中间查询结果 (语句 " + statementCount + ") ---");
                    if (results != null && !results.isEmpty()) {
                        for (String[] row : results) {
                            System.out.println(Arrays.toString(row));
                        }
                    } else {
                        System.out.println("(无结果)");
                    }
                    System.out.println("--- 中间查询结果结束 ---");
                }
            }
            
            // 将最后一个语句的结果转换为ArrayList<ArrayList<String>>格式
            ArrayList<ArrayList<String>> convertedResults = new ArrayList<>();
            if (results != null) {
                for (String[] row : results) {
                    ArrayList<String> convertedRow = new ArrayList<>(Arrays.asList(row));
                    convertedResults.add(convertedRow);
                }
            }
            return convertedResults;
        } catch (Exception e) {
            System.err.println("执行查询失败: " + e.getMessage());
            // 如果活动事务存在，这里可以选择是否回滚。
            // 通常SELECT失败不直接回滚整个事务，但记录下来很重要。
            if (TransactionLogger.getInstance().isTransactionActive()) {
                System.err.println("查询在活动事务中失败。事务状态未改变，但可能需要手动回滚。");
            }
            return new ArrayList<>();
        }
    }

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    /**
     * 检查数据库访问权限
     * 确认当前用户是否有权限访问指定数据库
     *
     * @param ownerName 数据库所有者的名称
     * @param dbName 要访问的数据库名称
     * @return 如果有权限返回true，否则返回false
     */
    public boolean checkDatabaseAccess(String ownerName, String dbName) {
        if (this.username == null || dbName == null || dbName.isEmpty() || ownerName == null || ownerName.isEmpty()) {
            return false;
        }

        // 系统管理员(1级权限)对所有数据库都有权限 (包括system_db)
        if (UserManager.isAdmin(this.username)) {
            return true; 
        }
        
        // 对于普通用户访问 system_db (owner "system")，通常不允许
        if ("system_db".equals(dbName) && "system".equals(ownerName)) {
            return false; // 普通用户不能直接访问 system_db 的内部
        }
        
        // 检查是否是用户自己的数据库
        if (this.username.equals(ownerName)) {
            return true; // 用户可以访问自己的数据库
        }
        
        // 对于其他用户的数据库，检查是否有权限访问
        return storage.manager.DatabaseManager.hasDatabasePermission(this.username, ownerName, dbName);
    }

    // 处理CREATE DATABASE语句
    private int handleCreateDatabase(String sql) {
        try {
            // 解析SQL获取数据库名称
            Statement stmt = CCJSqlParserUtil.parse(sql);

            if (stmt instanceof CreateSchema createSchema) {
                // 执行创建并关联用户
                return SQLExecutor.executeCreateDatabase(createSchema, this.username);
            }
        } catch (Exception e) {
            // 如果解析失败，使用常规执行方式
            System.err.println("解析CREATE DATABASE语句失败，使用常规方式执行: " + e.getMessage());
        }

        return -1;
    }

    // 处理USE DATABASE语句
    private int handleUseDatabase(String sql) {
        try {
            // Regex for "USE dbName" or "USE dbName FROM ownerName" (optional semicolon)
            // Group 1: dbName, Group 3 (optional): ownerName
            Pattern pattern = Pattern.compile("USE\\s+([a-zA-Z0-9_]+)(?:\\s+FROM\\s+([a-zA-Z0-9_]+))?\\s*;?", Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(sql.trim());

            if (matcher.matches()) { // Use matches() for full string match
                String parsedDbName = matcher.group(1);
                String parsedOwnerName = matcher.group(2); // Might be null if FROM clause is absent

                System.out.println("[Session.handleUseDatabase] Parsed from SQL: dbName='" + parsedDbName + "', ownerName='" + (parsedOwnerName == null ? "null (will default to user)" : parsedOwnerName) + "'");

                if (parsedOwnerName == null || parsedOwnerName.trim().isEmpty()) {
                    parsedOwnerName = this.username; // Default to current user if FROM is not specified
                    System.out.println("[Session.handleUseDatabase] Owner defaulted to current user: '" + parsedOwnerName + "'");
                }

                // 1. 首先检查数据库是否存在 (通过 DatabaseManager) - assuming new signature
                System.out.println("[Session.handleUseDatabase] Calling DatabaseManager.databaseExists with Owner: '" + parsedOwnerName + "', DB Name: '" + parsedDbName + "'");
                if (!storage.manager.DatabaseManager.databaseExists(parsedOwnerName, parsedDbName)) {
                    throw new StorageException("数据库 [" + parsedOwnerName + "." + parsedDbName + "] 不存在");
                }

                // 2. 如果数据库存在，再检查用户是否有权限访问该数据库 - uses modified checkDatabaseAccess
                System.out.println("[Session.handleUseDatabase] Checking access for User: '" + this.username + "' to DB: '" + parsedOwnerName + "." + parsedDbName + "'");
                if (!checkDatabaseAccess(parsedOwnerName, parsedDbName)) {
                    throw new StorageException("用户 [" + username + "] 无权访问数据库 [" + parsedOwnerName + "." + parsedDbName + "]");
                }

                // 3. 检查是否有活动的事务，如果有且与要切换的数据库不一致，先回滚它
                TransactionLogger txLogger = TransactionLogger.getInstance();
                if (txLogger.isTransactionActive()) {
                    String currentTxOwner = txLogger.getTransactionOwnerName();
                    String currentTxDb = txLogger.getTransactionDatabaseName();
                    
                    if (currentTxDb != null && (!currentTxDb.equals(parsedDbName) || 
                        (currentTxOwner != null && !currentTxOwner.equals(parsedOwnerName)))) {
                        System.out.println("警告: 检测到活动事务与要切换的数据库不一致。当前事务: " + 
                            currentTxOwner + "." + currentTxDb + ", 要切换到: " + 
                            parsedOwnerName + "." + parsedDbName + ". 执行回滚。");
                        txLogger.rollbackTransaction();
                    }
                }

                // 4. 设置当前数据库 - uses modified setCurrentDatabase
                System.out.println("[Session.handleUseDatabase] Calling setCurrentDatabase with Owner: '" + parsedOwnerName + "', DB Name: '" + parsedDbName + "'");
                boolean success = setCurrentDatabase(parsedOwnerName, parsedDbName);
                if (!success) {
                    throw new StorageException("无法设置当前数据库: " + parsedOwnerName + "." + parsedDbName + ". 请查看控制台输出获取详细错误信息。");
                }

                // 5. 成功设置当前数据库后，为此数据库启动事务 - assuming new signature for beginTransaction
                try {
                    System.out.println("[Session.handleUseDatabase] Starting transaction for User: '" + this.username + "', DB Owner: '" + 
                        this.currentDatabaseOwnerName + "', DB Name: '" + this.currentDatabaseName + "'");
                    
                    boolean txStarted = txLogger.beginTransaction(this.currentDatabaseOwnerName, this.currentDatabaseName); 
                    
                    if (!txStarted) {
                        throw new Exception("事务启动失败");
                    }
                    
                    // 验证事务是否确实已启动且与当前数据库一致
                    if (!txLogger.isTransactionActive() || 
                        !this.currentDatabaseName.equals(txLogger.getTransactionDatabaseName()) ||
                        !this.currentDatabaseOwnerName.equals(txLogger.getTransactionOwnerName())) {
                        
                        throw new Exception("事务验证失败: 活动=" + txLogger.isTransactionActive() + 
                            ", 事务DB=" + txLogger.getTransactionDatabaseName() + 
                            ", 事务Owner=" + txLogger.getTransactionOwnerName() + 
                            ", 但会话DB=" + this.currentDatabaseName + 
                            ", 会话Owner=" + this.currentDatabaseOwnerName);
                    }
                } catch (Exception e) {
                    System.err.println("处理USE语句时，为数据库 " + parsedOwnerName + "." + parsedDbName + " 启动事务失败: " + e.getMessage());
                    this.currentDatabaseName = null; 
                    this.currentDatabaseOwnerName = null;
                    storage.manager.DatabaseManager.setCurrentDatabase(null, null); 
                    System.err.println("由于事务启动失败，已重置会话的当前数据库选择。");
                    throw new StorageException("为数据库 " + parsedOwnerName + "." + parsedDbName + " 启动事务失败: " + e.getMessage(), e);
                }

                System.out.println("[DEBUG] 当前数据库已设置为: " + this.currentDatabaseOwnerName + "." + this.currentDatabaseName + " 并且事务已启动。");
                return 1; // 成功
            } else {
                throw new Exception("无效的USE语句格式。预期格式: USE <dbName> [FROM <ownerName>];");
            }
        } catch (StorageException e) { 
            System.err.println("切换数据库失败: " + e.getMessage());
            return -1;
        } catch (Exception e) { 
            System.err.println("处理USE语句时发生错误: " + e.getMessage());
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            System.err.println("堆栈跟踪:\n" + sw.toString().replace("\t", "    "));
            return -1;
        }
    }

    /**
     * 显示当前用户拥有的所有数据库
     * 调用DatabaseManager获取和显示用户数据库列表
     */
    public void showUserDatabases() {
        storage.manager.DatabaseManager.showDatabases(this.username);
    }

    /**
     * 删除当前用户拥有的数据库
     * 调用DatabaseManager的deleteDatabase方法删除数据库
     * 
     * @param dbName 要删除的数据库名称
     * @return 操作结果，1表示成功，0表示失败
     */
    public int deleteDatabase(String dbName) {
        try {
            // 获取当前会话的用户名作为 ownerName
            String ownerName = this.getUsername(); 
            if (ownerName == null) {
                System.err.println("❌ 删除数据库失败: 无法确定数据库所有者 (用户未正确登录或会话无效)。");
                return 0;
            }

            // 调用DatabaseManager删除数据库，传入 ownerName 和 dbName
            int result = storage.manager.DatabaseManager.deleteDatabase(ownerName, dbName);
            
            // 如果删除的是当前数据库，重置当前数据库
            // This logic is for the non-SQL "delete_db" command which targets user's own DBs.
            // The currentDatabaseName and currentDatabaseOwnerName might point to another user's DB if USE was used.
            // So, this check correctly ensures we only clear context if the deleted DB was the *user's own* and also the *current* one.
            if (result == 1 && dbName.equals(this.currentDatabaseName) && ownerName.equals(this.currentDatabaseOwnerName)) {
                this.currentDatabaseName = null; 
                this.currentDatabaseOwnerName = null;
                storage.manager.DatabaseManager.setCurrentDatabase(null,null); // Also notify DBManager
                System.out.println("ℹ️ 当前会话的数据库设置已清除，因为数据库 '" + ownerName + "." + dbName + "' 已被删除。");
            }
            
            return result;
        } catch (Exception e) {
            System.err.println("❌ 删除数据库失败: " + e.getMessage());
            return 0;
        }
    }

    /**
     * Clears the current database context for this session, typically after a transaction rollback.
     * This ensures the session state reflects that no database is actively selected if a transaction failed.
     */
    public void clearCurrentDatabaseAfterRollback() {
        if (this.currentDatabaseName != null) { 
            System.out.println("[INFO] Session: Transaction for database '" + this.currentDatabaseOwnerName + "." + this.currentDatabaseName + "' was rolled back. Clearing current database context for session.");
        } else {
            System.out.println("[INFO] Session: Transaction (potentially without a selected database) was rolled back. Ensuring session database context is clear.");
        }
        this.currentDatabaseName = null; 
        this.currentDatabaseOwnerName = null;
        // 也许也需要通知 DatabaseManager 清除上下文
        storage.manager.DatabaseManager.setCurrentDatabase(null, null); 
        System.out.println("ℹ️ 由于事务回滚，当前数据库上下文已清除。");
    }

    /**
     * 获取指定表的结构描述信息。
     *
     * @param tableName 要描述的表名。
     * @return 表的结构信息列表，每行为一个字符串数组 [列名, 类型, 是否可为空, 默认值, 主键]。
     *         如果当前未选择数据库，或表不存在，则返回null或包含错误信息的列表。
     */
    public List<String[]> describeTable(String tableName) {
        if (this.currentDatabaseName == null) {
            System.err.println("❌ 错误: 未选择数据库。请先使用 USE DATABASE 命令选择数据库。");
            List<String[]> errorResult = new ArrayList<>();
            errorResult.add(new String[]{"ERROR", "No database selected. Use 'USE DATABASE' first.", "", "", ""});
            return errorResult;
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            System.err.println("❌ 错误: 表名不能为空。");
            List<String[]> errorResult = new ArrayList<>();
            errorResult.add(new String[]{"ERROR", "Table name cannot be empty.", "", "", ""});
            return errorResult;
        }

        // 确保在事务上下文中执行，因为 DataManager 的方法现在需要它
        TransactionLogger txLogger = TransactionLogger.getInstance();
        if (!txLogger.isTransactionActive()) {
            System.out.println("ℹ️ describeTable: 当前无活动事务，将启动一个只读事务。");
            // 注意：DESCRIBE 通常是只读的，但 DataManager 的实现依赖事务上下文
            // 这里启动一个"临时"或"只读"事务的概念可能需要更细致的事务管理设计
            // 为简化，我们假设 TransactionLogger 能处理这种情况或已在外部处理
            // 如果 txLogger.startTransactionIfNeeded() 之类的方法存在会更好
            // 否则，如果必须在事务中，外部调用者（如SQLParser）需要确保事务已启动
             txLogger.beginTransaction(this.username, this.currentDatabaseName); // 使用 this.username 和 this.currentDatabaseName
        }

        List<String[]> description = storage.data.DataManager.getTableDescription(this.currentDatabaseName, tableName);
        
        // 如果上面启动了临时事务，这里可能需要提交或回滚（对于只读操作通常是回滚或无操作提交）
        // if (weStartedTemporaryTransaction) txLogger.commitTransaction(); // or rollback for read-only

        return description;
    }
}
